/*****************************************************************************
** Function name:   ADCInit
**
** Descriptions:    initialize ADC channel
**
** parameters:      ADC clock rate
** Returned value:    true or false
**
*****************************************************************************/

#include <nxp/iolpc2378.h>
#include <stdint.h>
#include "../misc/arm_comm.h"
#include "adc.h"

#define Fpclk 14000000

void ADCInit( uint32_t ADC_Clk )
{
  /* Enable CLOCK into ADC controller */
  PCONP |= (1 << 12);

  /* all the related pins are set to ADC inputs, AD0.0~7 */
  PINSEL0 |= 0x300000;  /* P0.12~13, A0.6~7, function 11 */
  
  volatile uint32_t pinsel1_reg = PINSEL1;
  pinsel1_reg |= 0x28000;
  pinsel1_reg &= ~(0x14000000);

  PINSEL1 = pinsel1_reg;

  AD0CR = ( 0x01 << 0 ) |   /* SEL=1,select channel 0~7 on ADC0 */
          ( ( Fpclk / ADC_Clk - 1 ) << 8 ) |  /* CLKDIV = Fpclk / 1000000 - 1 */
          ( 0 << 16 ) |     /* BURST = 0, no BURST, software controlled */
          ( 0 << 17 ) |     /* CLKS = 0, 11 clocks/10 bits */
          ( 1 << 21 ) |     /* PDN = 1, normal operation */
          ( 0 << 22 ) |     /* TEST1:0 = 00 */
          ( 0 << 24 ) |     /* START = 0 A/D conversion stops */
          ( 0 << 27 );      /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */
}

/*****************************************************************************
** Function name:   ADC0Read
**
** Descriptions:    Read ADC0 channel
**
** parameters:      Channel number
** Returned value:    Value read, if interrupt driven, return channel #
**
*****************************************************************************/
uint32_t ADC0Read( uint8_t channelNum )
{
uint32_t regVal, ADC_Data;


  /* channel number is 0 through 7 */
  if ( channelNum >= ADC_NUM )
  {
    channelNum = 0;   /* reset channel number to 0 */
  }
  AD0CR &= 0xFFFFFF00;
  AD0CR |= (1 << 24) | (1 << channelNum);
  /* switch channel,start A/D convert */

  while ( 1 )     /* wait until end of A/D convert */
  {
    regVal = *(volatile unsigned long *)(AD0_BASE_ADDR
    + ADC_OFFSET + ADC_INDEX * channelNum);
    /* read result of A/D conversion */
    if ( regVal & ADC_DONE )
    {
      break;
    }
  }

  AD0CR &= 0xF8FFFFFF;  /* stop ADC now */
  if ( regVal & ADC_OVERRUN ) /* save data when it's not overrun, otherwise, return zero */
  {
    return ( 0 );
  }
  ADC_Data = ( regVal >> 6 ) & 0x3FF;
  return  ADC_Data ;  /* return A/D conversion value */

}

/*********************************************************************************
**                            End Of File
*********************************************************************************/
